﻿// 디버깅용으로 서버와 인증 및 데이터 통신하지 않으려면 아래 주석을 풀 것
//#define NO_TRANSDATA

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Runtime.InteropServices;
using System.Net.NetworkInformation;

namespace LicenseAutoDetection
{
    static class Define
    {
        public const int STX = 0x02;
        public const int ETX = 0x03;

        public const int DELETE = 1;
        public const int EXCEPT = 2;

        public const string ENDPOINT_IP = "39.116.224.105";
        public const int ENDPOINT_PORT = 33579;
    }

    public class TransData
    {
        public struct DataInfo
        {
            public int FilePathLength;
            public int FileNameLength;
            public string FileFullName;
            public string FilePath;
            public string FileName;
            public string ModifyDate;
            public int InfoType;
        }
        List<DataInfo> Passed = new List<DataInfo>();
        List<DataInfo> Deleted = new List<DataInfo>();
        List<DataInfo> Ignored = new List<DataInfo>();
        List<String> Type = new List<String>();
        
        SendData S_Data = new SendData();
        Registeration regi = new Registeration();
        FileInfo fileinfo;

        public byte[] outData = new byte[512];
        public RecvData R_Data = new RecvData();
        public IPEndPoint EndPoint = new IPEndPoint(IPAddress.Parse(Define.ENDPOINT_IP), Define.ENDPOINT_PORT);

        public TransData()     // 서버에 등록이 되있는 pc 인지 확인
        {
#if (!NO_TRANSDATA)
            Socket sendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //registration_chk regi = new registration_chk();
            SendData registdata = new SendData();

            registdata.setPCode(regi.ReadPCode());
            registdata.setCommand("C");

            sendSocket.Connect(EndPoint);
            sendSocket.Send(registdata.getByte());

            sendSocket.Receive(outData, 512, SocketFlags.None);
            R_Data.DATETIME = DataConvert.Slice(outData, 2, 16, "I");
            R_Data.CMD = DataConvert.Slice(outData, 16, 17, "C");
            R_Data.P_CODE = DataConvert.Slice(outData, 17, 23, "C");
            R_Data.Response = outData[23];
/*
            if (R_Data.Response == 1)
            {
                MessageBox.Show("인증되었습니다", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                MessageBox.Show("인증에 실패했습니다, PCODE를 등록 해주세요.", "", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
*/
            sendSocket.Shutdown(SocketShutdown.Both);
            sendSocket.Close();
            sendSocket = null;
#else
            outData[23] = 1;
#endif
        }

        public TransData(String CMD, String PCODE, String DATA) 
        {
#if (!NO_TRANSDATA)
            Socket sendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //registration_chk regi = new registration_chk();
            SendData registdata = new SendData();

            registdata.setPCode(PCODE);
            registdata.setCommand(CMD);

            if (CMD == "B")
            {
                registdata.setCRN(DATA);
            }
            else if (CMD == "M")
            {
                registdata.setPhone(DATA);
            }
            else if (CMD == "R")
            {
                registdata.setNickName(DATA);
            }

            sendSocket.Connect(EndPoint);
            sendSocket.Send(registdata.getByte());

            sendSocket.Receive(outData, 512, SocketFlags.None);
            R_Data.DATETIME = DataConvert.Slice(outData, 2, 16, "I");
            R_Data.CMD = DataConvert.Slice(outData, 16, 17, "C");
            R_Data.P_CODE = DataConvert.Slice(outData, 17, 23, "C");
            R_Data.Response = outData[23];

            if (CMD == "B")
            {
                //상호명
                R_Data.BusiName = DataConvert.Slice(outData, 24, 24 + outData[23], "C");
                R_Data.BusiNameLen = outData[23];
            }
            else if (CMD == "M")
            {
                //인증번호
                R_Data.CertNum = DataConvert.Slice(outData, 23, 29, "I");
            }
            else if (CMD == "R")
            {
                //응답
                R_Data.Response = outData[23];
            }

            sendSocket.Shutdown(SocketShutdown.Both);
            sendSocket.Close();
            sendSocket = null;
#endif
        }

        public void TransmissionAnaly()  // 분석결과 전송
        {
#if (!NO_TRANSDATA)
            Socket sendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            sendSocket.Connect(EndPoint);
            int cnt = 0;
            foreach (DataInfo file in Passed)
            {
                if (File.Exists(file.FileFullName))
                {
                    //MessageBox.Show(file.FileName + regi.FO_func(), "", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    S_Data.setPCode(regi.ReadPCode());
                    S_Data.setCommand("O");
                    S_Data.setFilePath(file.FilePath);
                    S_Data.setFileName(file.FileName);
                    S_Data.setModifyDate(file.ModifyDate);
                    S_Data.setType(Type[cnt++]);

                    byte[] inData = S_Data.getByte();

                    try
                    {
                        sendSocket.Send(inData, inData.Length, SocketFlags.None);
                    }
                    catch
                    {
                        sendSocket.Connect(EndPoint);
                        sendSocket.Send(inData, inData.Length, SocketFlags.None);
                    }

                    System.Threading.Thread.Sleep(100);
                }
            }
            sendSocket.Shutdown(SocketShutdown.Both);
            sendSocket.Close();
            sendSocket = null;
#endif
        }

        public void TransmissionIgnored()
        {
#if (!NO_TRANSDATA)
            Socket sendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            sendSocket.Connect(EndPoint);

            foreach (DataInfo file in Ignored)
            {
                if (File.Exists(file.FileFullName))
                {
                    S_Data.setPCode(regi.ReadPCode());
                    S_Data.setCommand("D");

                    S_Data.setFilePath(file.FilePath);
                    S_Data.setFileName(file.FileName);
                    S_Data.setModifyDate(file.ModifyDate);
                    S_Data.setHandle(Define.EXCEPT);

                    byte[] inData = S_Data.getByte();

                    try
                    {
                        sendSocket.Send(inData, inData.Length, SocketFlags.None);
                    }
                    catch
                    {
                        sendSocket.Connect(EndPoint);
                        sendSocket.Send(inData, inData.Length, SocketFlags.None);
                    }

                    System.Threading.Thread.Sleep(100);
                }
            }
            sendSocket.Shutdown(SocketShutdown.Both);
            sendSocket.Close();
            sendSocket = null;
#endif
        }

        public void TransmissionDel()   // 삭제 결과 전송
        {
#if (!NO_TRANSDATA)
            Socket sendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            sendSocket.Connect(EndPoint);
            foreach (DataInfo file in Deleted)
            {
                if (!File.Exists(file.FileFullName))
                {
                    S_Data.setPCode(regi.ReadPCode());
                    S_Data.setCommand("D");

                    S_Data.setFilePath(file.FilePath);
                    S_Data.setFileName(file.FileName);
                    S_Data.setModifyDate(file.ModifyDate);
                    S_Data.setHandle(Define.DELETE);

                    byte[] inData = S_Data.getByte();

                    try
                    {
                        sendSocket.Send(inData, inData.Length, SocketFlags.None);
                    }
                    catch
                    {
                        sendSocket.Connect(EndPoint);
                        sendSocket.Send(inData, inData.Length, SocketFlags.None);
                    }

                    System.Threading.Thread.Sleep(100);
                }
            }
            sendSocket.Shutdown(SocketShutdown.Both);
            sendSocket.Close();
            sendSocket = null;
#endif
        }
        public void PassedTypeADD(InfoType In_Type)
        {
            String temp;
            Type.Add(In_Type.ToString());
            temp = Type[0];
        }

        public string PassedAdd
        {
            set
            {
                try
                {
                    if (File.Exists(value.ToString()))
                    {
                        Passed.Add(ExtractionFileInfo(value.ToString()));
                    }
                }
                catch
                {
                    // do nothing
                }
            }
        }

        public string IgnoredAdd
        {
            set
            {
                try
                {
                    if (File.Exists(value.ToString()))
                    {
                        Ignored.Add(ExtractionFileInfo(value.ToString()));
                    }
                }
                catch
                {
                    // do nothing
                }
            }
        }

        public string DeletedAdd
        {
            set
            {
                try
                {
                    if (File.Exists(value.ToString()))
                    {
                        Deleted.Add(ExtractionFileInfo(value.ToString()));
                    }
                }
                catch
                {
                    // do nothing
                }
            }
            get
            {
                try
                {
                    DataInfo ErrDelted = Deleted[Deleted.Count-1];
                    return ErrDelted.FileFullName;
                }
                catch
                {
                    return "";
                }
            }
        }

        public void DeletedRemove()
        {
            try
            {
                Deleted.RemoveAt(Deleted.Count - 1);
            }
            catch
            {

            }
        }

        public void PassedClear()
        {
            Passed.Clear();
        }

        public void IgnoredClear()
        {
            Ignored.Clear();
        }

        public void DeletedClear()
        {
            Deleted.Clear();
        }

        private DataInfo ExtractionFileInfo(string path)
        {
            DataInfo dataInfo = new DataInfo();

            fileinfo = new FileInfo(path);
            dataInfo.FileFullName = fileinfo.FullName;
            dataInfo.FilePathLength = fileinfo.DirectoryName.Length;
            dataInfo.FileNameLength = fileinfo.Name.Length;
            dataInfo.FilePath = fileinfo.DirectoryName;
            dataInfo.FileName = fileinfo.Name;
            DateTime FileLastWriteTime = fileinfo.LastWriteTime;
            dataInfo.ModifyDate = FileLastWriteTime.Year.ToString() + DateLength(FileLastWriteTime.Month) +
                       DateLength(FileLastWriteTime.Day) + DateLength(FileLastWriteTime.Hour) + DateLength(FileLastWriteTime.Minute) +
                       DateLength(FileLastWriteTime.Second);
            return dataInfo;
        }

        private string DateLength(int date)
        {
            string str;
            if (date > 9)
                str = date.ToString();
            else
                str = "0" + date.ToString();
            return str;
        }

    }

    public class CMacAddressManager    // MAC 주소 가져오는 클래스
    {
        private static CMacAddressManager instance;
        private String address;

        private CMacAddressManager()
        {
            NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
            address = String.Empty;

            foreach (NetworkInterface adapter in adapters)
            {
                PhysicalAddress pa = adapter.GetPhysicalAddress();

                if ((pa != null) && (!pa.ToString().Equals("")))
                {
                    address = pa.ToString();
                    break;
                }
            }
        }

        public static String Address
        {
            get
            {
                if (instance == null)
                    instance = new CMacAddressManager();

                return instance.address;
            }
        }
    }

    public static class DataConvert
    {
        //Int -> Char 형 변환
        public static String IntCharCast(int Num)
        {
            return (char)Num + "";
        }

        //숫자 문자열 -> INT -> Char 형변환
        public static String StringIntCharCast(String Num)
        {
            char[] NumArr = Num.ToCharArray();
            String tmp = "";
            for (int i = 0; i < NumArr.Length; i++)
            {
                tmp += IntCharCast(Convert.ToInt32(NumArr[i] + ""));
            }
            return tmp;
        }

        //Int 배열 -> 문자열 형 변환
        public static String IntArrStringCast(int[] IntArr)
        {
            String tmp = "";
            for (int i = 0; i < IntArr.Length; i++)
            {
                tmp += IntCharCast(IntArr[i]);
            }

            return tmp;
        }

        public static int ByteLength(String str)
        {
            byte[] bt = Encoding.Default.GetBytes(str);
            return bt.Length;
        }

        public static byte[] MACToByte(String hex)
        {
            byte[] btHex = new byte[6];
            for (int i = 0; i < hex.Length / 2; i++)
            {
                btHex[i] = (byte)(Int32.Parse(hex.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber));
            }

            return btHex;
        }

        public static int[] DefineETX(int size)
        {
            int[] SZ = new int[3];
            SZ[0] = size / 100;
            SZ[1] = (size % 100) / 10;
            SZ[2] = size % 10;

            return SZ;
        }

        public static String Slice(byte[] btCode, int start, int end, String mode)
        {
            byte[] bt = new byte[end - start];

            for (int i = 0; i < (end - start); i++)
            {
                bt[i] = btCode[start + i];
            }

            String tmp = "";
            if (mode.Equals("H"))
            { //16진 코드
                for (int i = 0; i < bt.Length; i++) tmp += String.Format("{0,X}", (int)bt[i]);
            }
            if (mode.Equals("I"))
            { //숫자형태
                for (int i = 0; i < bt.Length; i++) tmp += (int)bt[i] + "";
            }
            if (mode.Equals("C"))
            { //문자열 형태
                tmp = Encoding.Default.GetString(bt);
            }
            return tmp;
        }
    }       // 데이터 변형 클래스
	
    public class RecvData // 수신용 데이터
    {
        const int ETX_BASIC = 25;   //최소 ETX위치
        public int[] ETX_P = new int[3];

        public String DATETIME = "";   //날짜 및 시간
        public String CMD = "";        //명령어
        public String P_CODE = "";     //판매점 코드
        public String MAC;

        public String BusiName = "";   //상호명
        public int BusiNameLen = 0;   //상호명 길이

        public String CertNum = "";    //SMS인증번호

        public int Response = 0;       //응답코드

    }

    public class SendData             // 데이터 송신용 클래스
    {
        const int ETX_BASIC = 25;   //최소 ETX위치

        int[] ETX_P = new int[3];
        String DATETIME = "";   //날짜 및 시간
        String CMD = "";        //명령어
        String P_CODE = "";     //판매점 코드

        String CRN = "";        //사업자번호

        String PHONE = "";      //연락처
        String MAC = "";        //MAC주소

        String NickName = "";   //사용PC 별칭
        int NickNameLen = 0;

        String WithDraw = "";   //인증철회 사유
        int WithDrawLen = 0;

        String FilePath = "";   //파일경로
        int FilePathLen = 0;

        String FileName = "";   //파일이름
        int FileNameLen = 0;

        String ModifyDate = ""; //수정날짜
        int[] Info_Type = new int[5];//개인정보 형태

        int Handling = 0;       //파일 처리

        public SendData() { }
        public void setCommand(String cmd)
        {
            CMD = cmd;
        }
        public void setPCode(String code)
        {
            P_CODE = code;
        }
        public void setCRN(String crn)
        {
            CRN = crn;
        }
        public void setPhone(String phone)
        {
            if (phone.Length == 10) PHONE = phone + "X";
            else PHONE = phone;
        }
        public void setNickName(String nick)
        {
            NickName = nick;
            NickNameLen = DataConvert.ByteLength(nick);
        }
        public void setWithDraw(String draw)
        {
            WithDraw = draw;
            WithDrawLen = DataConvert.ByteLength(draw);
        }
        public void setFilePath(String path)
        {
            FilePath = path;
            FilePathLen = DataConvert.ByteLength(path);
        }
        public void setFileName(String file)
        {
            FileName = file;
            FileNameLen = DataConvert.ByteLength(file);
        }
        public void setModifyDate(String modify)
        {
            ModifyDate = modify;
        }
        public void setHandle(int handle)
        {
            Handling = handle;
        }
        public void setType(String type)
        {
            if (type.Equals("Identification"))
                Info_Type[0] = 1;
            else if (type.Equals("Contract"))
                Info_Type[0] = 2;
            else if (type.Equals("ResidentNum"))
                Info_Type[0] = 3;
            else if (type.Equals("PhoneNum"))
                Info_Type[0] = 4;

            for (int i = 1; i < Info_Type.Length; i++)
                Info_Type[i] = 0;
            /*Type = DCV.StringToIntArr(type);*/
        }
        public byte[] getByte()
        {
            byte[] btCode = new byte[1024];
            int idx = 0;
            //현재시간
            DATETIME = DateTime.Now.ToString("yyyyMMddHHmmss");

            //맥주소
            MAC = CMacAddressManager.Address;

            byte[] btMac = DataConvert.MACToByte(MAC);

            String BasicData = "";

            BasicData = DataConvert.StringIntCharCast(DATETIME) + CMD + P_CODE;

            byte[] btBasic = Encoding.Default.GetBytes(BasicData);

            for (int i = 0; i < btBasic.Length; i++)
            {
                btCode[idx] = btBasic[i];
                idx++;
            }

            if (CMD.Equals("B"))
            {
                ETX_P = DataConvert.DefineETX(ETX_BASIC + 10);

                byte[] btCrn = Encoding.Default.GetBytes(DataConvert.StringIntCharCast(CRN));
                for (int i = 0; i < btCrn.Length; i++)
                {
                    btCode[idx] = btCrn[i];
                    idx++;
                }
            }
            else if (CMD.Equals("M"))
            {
                ETX_P = DataConvert.DefineETX(ETX_BASIC + 11);

                byte[] btPhone = Encoding.Default.GetBytes(PHONE);

                for (int i = 0; i < btPhone.Length; i++)
                {
                    btCode[idx] = btPhone[i];
                    idx++;
                }
            }
            else if (CMD.Equals("R"))
            {
                ETX_P = DataConvert.DefineETX(ETX_BASIC + 6 + 1 + NickNameLen);

                for (int i = 0; i < btMac.Length; i++)
                {
                    btCode[idx] = btMac[i];
                    idx++;
                }
                btCode[idx] = (byte)NickNameLen;
                idx++;

                byte[] btNickName = Encoding.Default.GetBytes(NickName);

                for (int i = 0; i < btNickName.Length; i++)
                {
                    btCode[idx] = btNickName[i];
                    idx++;
                }
            }
            else if (CMD.Equals("C"))
            {
                ETX_P = DataConvert.DefineETX(ETX_BASIC + 6);

                for (int i = 0; i < btMac.Length; i++)
                {
                    btCode[idx] = btMac[i];
                    idx++;
                }
            }
            else if (CMD.Equals("W"))
            {
                ETX_P = DataConvert.DefineETX(ETX_BASIC + 6 + 1 + WithDrawLen);

                for (int i = 0; i < btMac.Length; i++)
                {
                    btCode[idx] = btMac[i];
                    idx++;
                }

                btCode[idx] = (byte)WithDrawLen;
                idx++;

                byte[] btWithDraw = Encoding.Default.GetBytes(WithDraw);

                for (int i = 0; i < btWithDraw.Length; i++)
                {
                    btCode[idx] = btWithDraw[i];
                    idx++;
                }
            }
            else if (CMD.Equals("O"))
            {
                ETX_P = DataConvert.DefineETX(ETX_BASIC + 6 + 1 + FilePathLen + 1 + FileNameLen + 14 + 5);

            for (int i = 0; i < btMac.Length; i++)
            {
                btCode[idx] = btMac[i];
                idx++;
            }

            btCode[idx] = (byte)FilePathLen;
            idx++;

            byte[] btFilePath = Encoding.Default.GetBytes(FilePath);

            for (int i = 0; i < btFilePath.Length; i++)
            {
                btCode[idx] = btFilePath[i];
                idx++;
            }

            btCode[idx] = (byte)FileNameLen;
            idx++;

            byte[] btFileName = Encoding.Default.GetBytes(FileName);

            for (int i = 0; i < btFileName.Length; i++)
            {
                btCode[idx] = btFileName[i];
                idx++;
            }

            byte[] btRemain = Encoding.Default.GetBytes(DataConvert.StringIntCharCast(ModifyDate) + DataConvert.IntArrStringCast(Info_Type));

                for (int i = 0; i < btRemain.Length; i++)
                {
                    btCode[idx] = btRemain[i];
                    idx++;
                }
            }
            else if (CMD.Equals("D"))
            {
                ETX_P = DataConvert.DefineETX(ETX_BASIC + 6 + 1 + FilePathLen + 1 + FileNameLen + 14 + 1);

                for (int i = 0; i < btMac.Length; i++)
                {
                    btCode[idx] = btMac[i];
                    idx++;
                }

                btCode[idx] = (byte)FilePathLen;
                idx++;

                byte[] btFilePath = Encoding.Default.GetBytes(FilePath);

                for (int i = 0; i < btFilePath.Length; i++)
                {
                    btCode[idx] = btFilePath[i];
                    idx++;
                }

                btCode[idx] = (byte)FileNameLen;
                idx++;

                byte[] btFileName = Encoding.Default.GetBytes(FileName);

                for (int i = 0; i < btFileName.Length; i++)
                {
                    btCode[idx] = btFileName[i];
                    idx++;
                }

                byte[] btRemain = Encoding.Default.GetBytes(DataConvert.StringIntCharCast(ModifyDate) + DataConvert.IntCharCast(Handling));

                for (int i = 0; i < btRemain.Length; i++)
                {
                    btCode[idx] = btRemain[i];
                    idx++;
                }
            }

            byte[] btSendByte = new byte[ETX_P[0] * 100 + ETX_P[1] * 10 + ETX_P[2] + 1];

            btSendByte[0] = (byte)Define.STX;
            for (int i = 0; i < 3; i++)
            {
                btSendByte[i + 1] = (byte)ETX_P[i];
            }

            for (int i = 4; i < btSendByte.Length - 1; i++)
            {
                btSendByte[i] = btCode[i - 4];
            }
            btSendByte[btSendByte.Length - 1] = (byte)Define.ETX;

            return btSendByte;

        }
    }
}

